﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using Common.Utilities;
using Common.Utilities.Dispatcher;
using Workflows.Components.DALC;

namespace Workflows.Components
{
    /// <summary>
    /// 
    /// </summary>
    public partial class ForLoopEditor : Form, IComponentEditor 
    {
        private object _ActivityNode;
        private ForLoopComponent _ForLoop;

        /// <summary>
        /// 
        /// </summary>
        public ForLoopEditor()
        {
            InitializeComponent();
        }

        private void ForLoopEditor_Load(object sender, EventArgs e)
        {
            this.cbo_DataType.Items.Clear();
            foreach(SimpleDataType dataType in Enum.GetValues(typeof(SimpleDataType)))
            {
                this.cbo_DataType.Items.Add(dataType.ToString());
            }

            foreach (DataGridViewRow dr in this.dv_GVars.Rows)
            {
                if (dr.IsNewRow)
                {
                    DataGridViewComboBoxCell cellDataType = (DataGridViewComboBoxCell)dr.Cells[1];
                    cellDataType.Items.Clear();
                    foreach (SimpleDataType dataType in Enum.GetValues(typeof(SimpleDataType)))
                        cellDataType.Items.Add(dataType.ToString());
                }
            }

            this.UpdateInitCodeBlock();
        }

        #region Implementation of IComponentEditor

        public event UpdateComponentSettings UpdateComponentSettingEvent;

        /// <summary></summary>
        public object OwnerActivityNode
        {
            get { return _ActivityNode;}
            set { _ActivityNode = value;}
        }

        /// <summary></summary>
        public Type WorkflowComponentType
        {
            get { return typeof (ForLoopComponent); }
        }

        /// <summary></summary>
        public void LoadSettings(GlobalVariable[] globalVars, WorkflowComponentBase[] fromComponents, object activityNode, WorkflowComponentBase wfComponent)
        {
            this._ActivityNode = activityNode;
            this._ForLoop = (ForLoopComponent) wfComponent;
            ForLoopInstruction instruction = (ForLoopInstruction) this._ForLoop.Instruction;
            this.dv_GVars.Rows.Clear();
            if(instruction.Vars !=null && instruction.Vars.Count>0)
            {
                foreach(GlobalVariable gVar in instruction.Vars.Values)
                {
                    DataGridViewRow dr = new DataGridViewRow();
                    DataGridViewTextBoxCell cellVarName=new DataGridViewTextBoxCell();
                    cellVarName.Value = gVar.VarName;
                    dr.Cells.Add(cellVarName);
                    DataGridViewComboBoxCell cellDataType=new DataGridViewComboBoxCell();
                    foreach(SimpleDataType dataType in Enum.GetValues(typeof(SimpleDataType)))
                    {
                        cellDataType.Items.Add(dataType.ToString());
                    }
                    cellDataType.Value = gVar.DataType.ToString();
                    dr.Cells.Add(cellDataType);
                    DataGridViewTextBoxCell cellValue=new DataGridViewTextBoxCell();
                    cellValue.Value = gVar.VarValue.ToString();
                    dr.Cells.Add(cellValue);
                    this.dv_GVars.Rows.Add(dr);
                }
            }
            this.SelectComboxValue(this.cbo_DataType, instruction.ForExpression.DataType.ToString());
            this.txt_VarName.Text = instruction.ForExpression.VarName;
            this.txt_From.Text = instruction.ForExpression.FromValue.ToString();
            this.txt_To.Text = instruction.ForExpression.ToValue.ToString();
            this.txt_Step.Text = instruction.ForExpression.Step.ToString();
            if (!string.IsNullOrEmpty(instruction.InitCodeBlock))
                this.rt_InitCode.Text = instruction.InitCodeBlock;
            this.txt_ConsoleApp.Text = instruction.ConsoleAppFilePath;
            if(!string.IsNullOrEmpty(instruction.ConsoleAppFilePath))
            {
                List<GlobalVariable> gVars = this.ReadGlobalVariablesFromWorkflowConsoleApp(instruction.ConsoleAppFilePath);
                this.dv_SubflowBindings.Rows.Clear();
                if (gVars != null && gVars.Count > 0)
                {
                    foreach (GlobalVariable gVar in gVars)
                    {
                        DataGridViewRow dr = new DataGridViewRow();
                        DataGridViewTextBoxCell cellTgt = new DataGridViewTextBoxCell();
                        cellTgt.Value = gVar.VarName;
                        dr.Cells.Add(cellTgt);
                        DataGridViewComboBoxCell cellSrc = new DataGridViewComboBoxCell();
                        foreach (string varName in instruction.Vars.Keys)
                            cellSrc.Items.Add(varName);
                        if (instruction.SubflowVarBindings != null && instruction.SubflowVarBindings.ContainsKey(gVar.VarName))
                            cellSrc.Value = instruction.SubflowVarBindings[gVar.VarName];
                        dr.Cells.Add(cellSrc);
                        this.dv_SubflowBindings.Rows.Add(dr);
                    }
                }
            }
            
        }

        private void SelectComboxValue(ComboBox comboBox, string value)
        {
            if(comboBox.Items.Count>0 && !string.IsNullOrEmpty(value))
            {
                for(int i=0;i<comboBox.Items.Count;i++)
                {
                    if(comboBox.Items[i].ToString()==value)
                    {
                        comboBox.SelectedIndex = i;
                        break;
                    }
                }
            }
        }

        /// <summary></summary>
        public void SaveSettings()
        {
            ForLoopInstruction instruction = (ForLoopInstruction) this._ForLoop.Instruction;
            instruction.ForExpression=new ForStatement(
                this.txt_VarName.Text,(SimpleDataType)Enum.Parse(typeof(SimpleDataType),this.cbo_DataType.Text),
                this.txt_From.Text, this.txt_To.Text, this.txt_Step.Text);
            instruction.InitCodeBlock = this.rt_InitCode.Text;
            instruction.ConsoleAppFilePath = this.txt_ConsoleApp.Text;
            instruction.Vars=new Dictionary<string, GlobalVariable>();
            foreach(DataGridViewRow dr in this.dv_GVars.Rows)
            {
                if(!dr.IsNewRow && dr.Cells[0].Value !=null)
                {
                    GlobalVariable gVar=new GlobalVariable(dr.Cells[0].Value.ToString(),
                        (SimpleDataType)Enum.Parse(typeof(SimpleDataType),dr.Cells[1].Value.ToString()),
                        dr.Cells[2].Value.ToString());
                    instruction.Vars.Add(gVar.VarName, gVar);
                }
            }
            instruction.SubflowVarBindings=new Dictionary<string, string>();
            foreach(DataGridViewRow dr in this.dv_SubflowBindings.Rows)
            {
                if(!dr.IsNewRow && dr.Cells[0].Value !=null && dr.Cells[1].Value!=null)
                {
                    instruction.SubflowVarBindings.Add(dr.Cells[0].Value.ToString(), dr.Cells[1].Value.ToString());
                }
            }

            this._ForLoop.Instruction = instruction;
        }

        /// <summary></summary>
        public TestResult Test()
        {
            throw new System.NotImplementedException();
        }

        #endregion

        private void btn_OK_Click(object sender, EventArgs e)
        {
            this.SaveSettings();

            if (this.UpdateComponentSettingEvent != null)
                this.UpdateComponentSettingEvent(this._ActivityNode, this._ForLoop);

            this.Close();
        }

        private void btn_Cancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btn_Browse_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg=new OpenFileDialog();
            dlg.Filter = "Exe files(*.exe)|*.exe|All files(*.*)|*.*";
            if(dlg.ShowDialog()==DialogResult.OK)
            {
                this.txt_ConsoleApp.Text = dlg.FileName;

                List<GlobalVariable> gVars = this.ReadGlobalVariablesFromWorkflowConsoleApp(dlg.FileName);
                this.dv_SubflowBindings.Rows.Clear();
                if(gVars !=null && gVars.Count>0)
                {
                    foreach(GlobalVariable gVar in gVars)
                    {
                        DataGridViewRow dr = new DataGridViewRow();
                        DataGridViewTextBoxCell cellTgt = new DataGridViewTextBoxCell();
                        cellTgt.Value = gVar.VarName;
                        dr.Cells.Add(cellTgt);
                        DataGridViewComboBoxCell cellSrc=new DataGridViewComboBoxCell();
                        foreach(DataGridViewRow dr1 in this.dv_GVars.Rows)
                        {
                            if(!dr1.IsNewRow && dr1.Cells[0].Value !=null)
                            {
                                cellSrc.Items.Add(dr1.Cells[0].Value.ToString());
                            }
                        }
                        dr.Cells.Add(cellSrc);
                        this.dv_SubflowBindings.Rows.Add(dr);
                    }
                }
            }
        }

        private void dv_GVars_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
        {
            foreach(DataGridViewRow dr in this.dv_GVars.Rows)
            {
                if(dr.IsNewRow)
                {
                    DataGridViewComboBoxCell cellDataType = (DataGridViewComboBoxCell)dr.Cells[1];
                    cellDataType.Items.Clear();
                    foreach (SimpleDataType dataType in Enum.GetValues(typeof(SimpleDataType)))
                        cellDataType.Items.Add(dataType.ToString());
                }
            }
        }

        private List<GlobalVariable> ReadGlobalVariablesFromWorkflowConsoleApp(string consoleAppFilePath)
        {
            List<GlobalVariable> gVars = new List<GlobalVariable>();
            string dirPath = Path.GetDirectoryName(consoleAppFilePath);
            string exeFileName = Path.GetFileNameWithoutExtension(consoleAppFilePath);
            string settingFilePath = Path.Combine(dirPath, exeFileName + ".xml");
            if (File.Exists(settingFilePath))
            {
                XmlDocument xDoc = new XmlDocument();
                xDoc.Load(settingFilePath);
                XmlNodeList varNodes = xDoc.DocumentElement.SelectNodes("GlobalVariables/Variable");
                if (varNodes != null && varNodes.Count > 0)
                {
                    foreach (XmlNode varNode in varNodes)
                    {
                        string varName = XmlDataUtil.GetAttributeValue(varNode, "VariableName", "");
                        SimpleDataType dataType =
                            (SimpleDataType)
                            int.Parse(XmlDataUtil.GetAttributeValue(varNode, "DataType",
                                                                    ((int)SimpleDataType.TextType).ToString()));
                        string varValue = XmlDataUtil.GetAttributeValue(varNode, "VariableValue", "");
                        gVars.Add(new GlobalVariable(varName, dataType, varValue));
                    }
                }
            }
            return gVars;
        }

        private void UpdateInitCodeBlock()
        {
            string classInitor = @"
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Common.Utilities;
using Common.Utilities.Dispatcher;
using Workflows.Components;

namespace Workflows.Components
{
    public class Initor
    {
        private Dictionary<string, GlobalVariable> _GlobalVariables;
        /// <summary></summary>
        public Dictionary<string, GlobalVariable> GlobalVariables
        {
            get
            {
                return this._GlobalVariables;
            }
            set
            {
                this._GlobalVariables = value;
            }
        }

        private GlobalVariable _ForVar;
        public GlobalVariable ForVar
        {
            get
            {
                return this._ForVar;
            }
            set 
            {
                this._ForVar=value;
            }
        }

        public Initor()
        {
        }

        public void Init()
        {
            // enter code here
        }
    }
}";
            this.rt_InitCode.Text = classInitor;
        }
    }
}
